<script setup lang="ts">
import { onMounted, onUnmounted, ref } from 'vue';
import { Base } from '../threejs/base';
import * as THREE from 'three';

class Demo extends Base {
  mesh:any;
  m: any;
  time:any;
  controls = { color: 0xff0000 };
  geometry = { Geometry:1};
  initGui() {
    const g = this.gui.addFolder('调整这里试试');
    let colorChange=g.addColor(this.controls, 'color').name('色值');
    let controller=g.add(this.geometry, 'Geometry', { PlaneGeometry: 1, BoxGeometry: 2, SphereGeometry: 3,ConeGeometry:4 } ).name('几何体');
    colorChange.onChange((value:any)=>{
      console.log(value)
      for(let i=0;i<this.scene.children.length;i++){
        // 方式1 
        // this.scene.children[i].material.uniforms.uColor.value.set(value); // 改变颜色为绿色
        // 方式2
        var newColor = new THREE.Color(this.controls.color);
        // 更新材质的颜色
        console.log(newColor)
        this.scene.children[i].material.uniforms.uColor.value.copy(newColor); // 如果颜色是uniform
      }
    })
    controller.onChange((value:any) =>{
      if(value==1){
        for(let i=0;i<this.scene.children.length;i++){
          this.scene.children[i].geometry=new THREE.PlaneGeometry(10,10,10)
        }
      }else if(value==2){
        for(let i=0;i<this.scene.children.length;i++){
          this.scene.children[i].geometry=new THREE.BoxGeometry(10,10,10)
        }
      }else if(value==3){
        for(let i=0;i<this.scene.children.length;i++){
          this.scene.children[i].geometry=new THREE.SphereGeometry(5,32,32)
        }
      }else if(value==4){
        for(let i=0;i<this.scene.children.length;i++){
          this.scene.children[i].geometry=new THREE.ConeGeometry(5,10,16)
        }
      }
    });
    g.open();
  }

  initShader() {
    // const g = new THREE.PlaneGeometry(100, 100);
    // const m = new THREE.ShaderMaterial({
    //   uniforms: {
    //     uColor: { value: new THREE.Color(this.controls.color) }
    //   },
    //   vertexShader: `
    //     varying vec2 vUv;
    //     void main() {
    //       vUv = uv;
    //       gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    //     }
    //   `,
    //   fragmentShader: `
    //     varying vec2 vUv;
    //     void main() {    
    //       vec3 color1 = vec3(1.0, 1.0, 0.0);
    //       vec3 color2 = vec3(0.0, 1.0, 1.0); 
    //       float mixer1 = (vUv.x + vUv.y);
    //       float mixer2 = 2.0 - (vUv.x + vUv.y);
    //       // float mixer = min(mixer1, mixer2);
    //       float mixer = mixer1*mixer2;

    //       vec3 color = mix(color1, color2, mixer);
    //       gl_FragColor = vUv.x>0.7&&vUv.y>0.2?vec4(vec3(0.5), 0.4):vec4(color1, 1.0);
    //     }
    //   `
    // });
    // const plane = new THREE.Mesh(g, m);
    // this.scene.add(plane);
    // this.m = m;
    // 创建一个几何体，相当于在画布上想要呈现的物体
    // const geometry = new THREE.BoxGeometry(80,80,80) 
    // const material = new THREE.MeshBasicMaterial({
    //   color:0x0000ff
    // })  
    // this.mesh = new THREE.Mesh(geometry,material)
    // this.scene.add(this.mesh)
    this.time=0
    this.ini01(-50,50,`
      varying vec2 vUv;
      void main() {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
      }
    `)
    this.ini01(-30,50,`
      varying vec2 vUv;
      void main() {
        // vUv.x => 0.0-1.0
        gl_FragColor = vec4(vUv.x, 0.0, 0.0, 1.0);
      }
    `)
    this.ini01(-10,50,`
      varying vec2 vUv;
      void main() {
        gl_FragColor = vec4(vUv.y, 0.0, 0.0, 1.0);
      }
    `)
    this.ini01(10,50,`
      varying vec2 vUv;
      void main() {
        gl_FragColor = vec4(vec3(vUv.x), 1.0);
      }
    `)
    this.ini01(30,50,`
      varying vec2 vUv;
      void main() {
        gl_FragColor = vec4(vUv.y, vUv.y, vUv.y, 1.0);
      }
    `)
    this.ini01(50,50,`
      varying vec2 vUv;
      void main() {
        gl_FragColor = vec4(vUv.x, vUv.y, 0.0, 1.0);
      }
    `)
    this.ini01(-50,30,`
      varying vec2 vUv;
      void main() {
        // step 返回一个bool值，如果为true则返回1.0，否则返回0.0
        float color = step(0.3, vUv.x);
        gl_FragColor = vec4(vec3(color), 1.0);
      }
    `)
    this.ini01(-30,30,`
      varying vec2 vUv;
      void main() {
        // fract 返回一个0-1的数，将x取余1，返回0-1的数
        gl_FragColor = vec4(vec3(fract(vUv.x * 3.0)), 1.0);
      }
    `)
    this.ini01(-10,30,`
      varying vec2 vUv;
      void main() {
        // fract 返回一个0-1的数，将x取余1，返回0-1的数
        gl_FragColor = vec4(vec3(step(0.5,fract(vUv.x * 3.0))), 1.0);
      }
    `)
    this.ini01(10,30,`
      varying vec2 vUv;
      void main() {
        // 绘制渐变圆形
        float dist = length(vUv);
        vec3 color = vec3(dist);
        gl_FragColor = vec4(color, 1.0);
      }
    `)

    this.ini01(30,30,`
      varying vec2 vUv;
      uniform float uTime;
      void main() {
        // 绘制渐变圆形
        float dist = length(vUv - vec2(0.5));
        float radius = 0.5 * (sin(uTime) * 0.5 + 0.5);
        vec3 color = vec3(step(radius,dist));
        
        gl_FragColor = vec4(color, 1.0);
      }
    `)
    this.ini01(50,30,`
      varying vec2 vUv;
      uniform float uTime;
      void main() {
        // 绘制渐变圆形
        float dist = length(fract(vUv * 5.0) - vec2(0.5));
        float radius = 0.5 * (sin(uTime) * 0.5 + 0.5);
        vec3 color = vec3(step(radius,dist));
        
        gl_FragColor = vec4(color, 1.0);
      }
    `)
    this.ini01(-50,10,`
      varying vec2 vUv;
      uniform float uTime;
      void main() {
        // 绘制渐变圆形
        float dist = length(fract(vUv * 5.0) - vec2(0.5));
        float radius = 0.5 * (sin(uTime+vUv.y) * 0.5 + 0.5);
        vec3 color = vec3(step(radius,dist));
        
        gl_FragColor = vec4(color, 1.0);
      }
    `)
    this.ini01(-30,10,`
      varying vec2 vUv;
      uniform float uTime;
      void main() {
        // 绘制渐变圆形
        float dist = length(fract(vUv * 5.0) - vec2(0.5));
        float radius = 0.5 * (sin(uTime+vUv.x+vUv.y) * 0.5 + 0.5);
        vec3 color = vec3(step(radius,dist));
        
        gl_FragColor = vec4(color, 1.0);
      }
    `)
    this.ini01(-50,-10,`
      varying vec2 vUv;
      uniform float uTime;
      void main() {
        float dist = fract((length(vUv - vec2(0.5))/ 0.707+ uTime * 0.1)  * 5.0);
        float radius = 0.5;
        vec3 color = vec3(step(radius,dist));
        
        gl_FragColor = vec4(color, 1.0);
      }
    `)
    this.ini01(-30,-10,`
      varying vec2 vUv;
      uniform float uTime;
      void main() {
        float dist = fract((length(vUv - vec2(0.5))/ 0.707- uTime * 0.1)  * 5.0);
        float radius = 0.5;
        vec3 color = vec3(step(radius,dist));
        
        gl_FragColor = vec4(color, 1.0);
      }
    `)

    this.ini01(-10,-10,`
      varying vec2 vUv;
      uniform vec3 uColor;
      uniform float uTime;
      void main() {
        vec3 color2 = vec3(0.0, 1.0, 0.0);
        float mixer = fract(vUv.x * 2.0);
        vec3 color = mix(uColor, color2, mixer);
        gl_FragColor = vec4(color, 1.0);
      }
    `)

    this.ini01(10,-10,`
      varying vec2 vUv;
      uniform vec3 uColor;
      uniform float uTime;
      void main() {
        vec3 color1 = vec3(1.0, 1.0, 0.0);
        vec3 color2 = uColor;
        float mask1 = step(0.5, fract(vUv.x * 3.0));
        float mask2 = step(0.5, fract(vUv.y * 3.0));
        float mixer = abs(mask1 - mask2);
        vec3 color = mix(color1, color2, mixer);
        gl_FragColor = vec4(color, 1.0);
      }
    `)
    this.ini01(-50,-30,`
      varying vec2 vUv;
      uniform vec3 uColor;
      uniform float uTime;
      void main() {
        // vec3 color1 = vec3(1.0, 1.0, 0.0);
        // vec3 color2 = uColor;
        // float mask1 = step(0.5, fract(vUv.x * 3.0));
        // float mask2 = step(0.5, fract(vUv.y * 3.0));
        // float mixer = abs(mask1 - mask2);
        // vec3 color = mix(color1, color2, mixer);
        // gl_FragColor = vec4(color, 1.0);
         gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
      }
    `,`
      uniform float uTime;
      varying vec2 vUv;
      void main() {
        vUv = uv;
        vec3 newPos = position;
        newPos.y += sin(position.y * (sin(uTime) + 1.0) * 5.0);
        gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);
      }
    `,true)
    this.ini01(-30,-30,`
      varying vec3 vNormal;
      varying vec2 vUv;
      uniform vec3 uColor;
      uniform float uTime;
      void main() {
        // vec3 color1 = vec3(1.0, 1.0, 0.0);
        // vec3 color2 = uColor;
        // float mask1 = step(0.5, fract(vUv.x * 3.0));
        // float mask2 = step(0.5, fract(vUv.y * 3.0));
        // float mixer = abs(mask1 - mask2);
        // vec3 color = mix(color1, color2, mixer);
        // gl_FragColor = vec4(color, 1.0);
         gl_FragColor = vec4(vNormal, 1.0);
      }
    `,`
      varying vec3 vNormal;
      //	Classic Perlin 3D Noise 
      //	by Stefan Gustavson
      vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);}
      vec4 taylorInvSqrt(vec4 r){return 1.79284291400159 - 0.85373472095314 * r;}
      vec3 fade(vec3 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);}

      float cnoise(vec3 P){
        vec3 Pi0 = floor(P); // Integer part for indexing
        vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1
        Pi0 = mod(Pi0, 289.0);
        Pi1 = mod(Pi1, 289.0);
        vec3 Pf0 = fract(P); // Fractional part for interpolation
        vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0
        vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x);
        vec4 iy = vec4(Pi0.yy, Pi1.yy);
        vec4 iz0 = Pi0.zzzz;
        vec4 iz1 = Pi1.zzzz;

        vec4 ixy = permute(permute(ix) + iy);
        vec4 ixy0 = permute(ixy + iz0);
        vec4 ixy1 = permute(ixy + iz1);

        vec4 gx0 = ixy0 / 7.0;
        vec4 gy0 = fract(floor(gx0) / 7.0) - 0.5;
        gx0 = fract(gx0);
        vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0);
        vec4 sz0 = step(gz0, vec4(0.0));
        gx0 -= sz0 * (step(0.0, gx0) - 0.5);
        gy0 -= sz0 * (step(0.0, gy0) - 0.5);

        vec4 gx1 = ixy1 / 7.0;
        vec4 gy1 = fract(floor(gx1) / 7.0) - 0.5;
        gx1 = fract(gx1);
        vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1);
        vec4 sz1 = step(gz1, vec4(0.0));
        gx1 -= sz1 * (step(0.0, gx1) - 0.5);
        gy1 -= sz1 * (step(0.0, gy1) - 0.5);

        vec3 g000 = vec3(gx0.x,gy0.x,gz0.x);
        vec3 g100 = vec3(gx0.y,gy0.y,gz0.y);
        vec3 g010 = vec3(gx0.z,gy0.z,gz0.z);
        vec3 g110 = vec3(gx0.w,gy0.w,gz0.w);
        vec3 g001 = vec3(gx1.x,gy1.x,gz1.x);
        vec3 g101 = vec3(gx1.y,gy1.y,gz1.y);
        vec3 g011 = vec3(gx1.z,gy1.z,gz1.z);
        vec3 g111 = vec3(gx1.w,gy1.w,gz1.w);

        vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110)));
        g000 *= norm0.x;
        g010 *= norm0.y;
        g100 *= norm0.z;
        g110 *= norm0.w;
        vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111)));
        g001 *= norm1.x;
        g011 *= norm1.y;
        g101 *= norm1.z;
        g111 *= norm1.w;

        float n000 = dot(g000, Pf0);
        float n100 = dot(g100, vec3(Pf1.x, Pf0.yz));
        float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z));
        float n110 = dot(g110, vec3(Pf1.xy, Pf0.z));
        float n001 = dot(g001, vec3(Pf0.xy, Pf1.z));
        float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z));
        float n011 = dot(g011, vec3(Pf0.x, Pf1.yz));
        float n111 = dot(g111, Pf1);

        vec3 fade_xyz = fade(Pf0);
        vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z);
        vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y);
        float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 
        return 2.2 * n_xyz;
      }
      void main() {
        vec3 newPos = position;
        newPos += normal * cnoise(position);
        vNormal = normal;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);
      }
    `,true)
    this.ini01(-10,-30,`
      varying vec3 vNormal;
      varying vec2 vUv;
      uniform vec3 uColor;
      uniform float uTime;
      void main() {
        // vec3 color1 = vec3(1.0, 1.0, 0.0);
        // vec3 color2 = uColor;
        // float mask1 = step(0.5, fract(vUv.x * 3.0));
        // float mask2 = step(0.5, fract(vUv.y * 3.0));
        // float mixer = abs(mask1 - mask2);
        // vec3 color = mix(color1, color2, mixer);
        // gl_FragColor = vec4(color, 1.0);
         gl_FragColor = vec4(vNormal, 1.0);
      }
    `,`
      varying vec3 vNormal;
      float random(vec3 pos){
        return fract(sin(dot(pos, vec3(64.25375463, 23.27536534, 86.29678483))) * 59482.7542);
      }
      void main() {
        vec3 newPos = position;
        newPos += normal * random(position);
        vNormal = normal;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(newPos, 1.0);
      }
    `)
  }
  ini01(x:any,y:any,fShader:any,vShader:any='',wireframe:any=false){
    console.log(vShader)
    const g = new THREE.PlaneGeometry(10, 10,10);
    const m = new THREE.ShaderMaterial({
      uniforms: {
        uColor: { value: new THREE.Color(this.controls.color) },
        uTime: { value: 0 } ,
      },
      vertexShader: vShader ||`
        varying vec2 vUv;
        void main() {
          vUv = uv;
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
      `,
      fragmentShader: fShader,
      wireframe: wireframe,

    });
    const plane = new THREE.Mesh(g, m);
    plane.position.x=x
    plane.position.y=y
    this.scene.add(plane);
  }
  renderContent() {
    // const currentTime = Date.now();
    // const deltaTime = currentTime - this.time;
    // this.time = currentTime;
    // // this.mesh.rotation.y = this.time/1000;
    // this.m.uniforms.uColor.value = new THREE.Color(this.controls.color);
    // geometry = new THREE.SphereGeometry(5, 32, 32); // 创建一个半径为5，分段数为32的球形几何体
    // mesh.geometry = geometry; // 将几何体应用于 Mesh 对象
    // this.geometry = geometry;
    this.time += 0.05;
    for(let i=0;i<this.scene.children.length;i++){
      this.scene.children[i].material.uniforms.uTime.value = this.time;
      // this.scene.children[i].rotation.y = this.time/10;
    }
  }
}

let ins: any;
const dom = ref();

onMounted(() => {
  ins = new Demo().init(dom.value);
});
onUnmounted(() => {
  ins.dispose();
});

const text = `
本示例主要学习了通过 uniforms 向着色器传递数据。示例主要代码如下：
\`\`\`
const m = new THREE.ShaderMaterial({
  uniforms: {
    uColor: { value: new THREE.Color(0xff0000) }
  },
  vertexShader: \`
    void main() {
      
      // position 是顶点的local坐标(Model坐标)
      // Model坐标 * ModelMatrix = World坐标；World坐标 * ViewMatrix = Camera坐标；Camera坐标 * ProjectionMatrix = 投影坐标

      gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    }\`,
  fragmentShader: \`
    uniform vec3 uColor;  // 接收 uniforms 传过来的数据
    
    void main() {
      gl_FragColor = vec4(uColor, 1.0);
    }\`
});
\`\`\`
`;
</script>

<template>
  <div class="shader-box" ref="dom"></div>
  <v-md-preview :text="text"></v-md-preview>
</template>

<style scoped></style>
